home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 415_02 / rtti / include / rttimacros.h < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-04  |  19.0 KB  |  473 lines

  1. #ifndef   _H_RTTI_MACROS
  2. #define   _H_RTTI_MACROS
  3.  
  4. /* %Z%%I%       %G% %U% %W% */
  5. /*
  6.  * COMPONENT_NAME: (COMINC) Common Header File for RTTI
  7.  *
  8.  * ORIGINS: 27
  9.  *
  10.  * (C) COPYRIGHT International Business Machines Corp. 1992
  11.  * This work was supported by a grant from International Business
  12.  * Machines, Inc. These procedures are contributed to the public domain
  13.  * by International Business Machines Inc. "AS IS" without any warranty
  14.  * of any kind including the warranty of merchantability or fitness
  15.  * for a particular purpose.
  16.  *
  17.  *
  18.  * This is free software. Feel free to redistribute and/or modify it.
  19.  * Please send us e-mail and let us know if you have any problems
  20.  * or suggestions.
  21.  *
  22.  * Arindam Banerji
  23.  * axb@cse.nd.edu
  24.  *
  25.  */
  26.  
  27.  
  28. // rttimacros.h
  29. // This file contains the macro definitions for automatically generating
  30. // the appropriate declarations (to be found within class declarations
  31. // or .h files) and the function/data definitions (to be found in class
  32. // definition files or .c files). There are different sets of macros
  33. // for generating these declarations and definitions for both non-template
  34. // and template classes. In most cases, the macros defined here are not
  35. // meant for human consumption. Either look at sample code or at a
  36. // document that explains the usage of these macros. A word of
  37. // warning is in order about the template macros - they have only been
  38. // been tested with cfront and xlC. Since, templates are notoriously
  39. // non-portable - these macros are not guaranteed to work with all
  40. // compilers.
  41.  
  42. /*****************
  43.    RTTI DECLARATION AND IMPLEMENTATION MACROS.
  44. ****************/
  45.  
  46. // macro definition to aid in the declaration of RTTI scaffolding
  47. // Use RTTI_SCAFFOLDING_DECL for non_template classes as in
  48. // class foo : public virtual CLASS. Use this macro in the .h file, within
  49. // the class declaration.
  50. #define  RTTI_SCAFFOLDING_DECL(TYPE)  \
  51.     static  const Type_info info_obj ; \
  52.     virtual typeid get_info() const ; \
  53.     virtual void   *get_this_ptr(void) const ; \
  54.     static  typeid  info() ; \
  55.     static  TYPE  *_narrow(CLASS *) ; \
  56.  
  57. // Use RTTI_SCAFFOLDING_DECL_TEMPL for template classes with just one
  58. // parameter. Again use this within the .h file.
  59. #define  RTTI_SCAFFOLDING_DECL_TEMPL(TYPE)  \
  60.     static  const Type_info info_obj ; \
  61.     virtual typeid get_info() const ; \
  62.     virtual void   *get_this_ptr(void) const ; \
  63.     static  typeid  info() ; \
  64.     static  TYPE  *_narrow(CLASS *) ; \
  65.     static const Type_info *base_set[] ; \
  66.  
  67. // Use RTTI_SCAFFOLDING_DECL_TEMPL_2 for template classes with two
  68. // parameters. Again use this within the .h file ie: for
  69. // template <class T, int n> class foo1 { .....
  70. // use RTTI_SCAFFOLDING_DECL_TEMPL_2(foo1,T,n)
  71. #define  RTTI_SCAFFOLDING_DECL_TEMPL_2(NAME,I1,I2)  \
  72.     static  const Type_info info_obj ; \
  73.     virtual typeid get_info() const ; \
  74.     virtual void   *get_this_ptr(void) const ; \
  75.     static  typeid  info() ; \
  76.     static  NAME<I1,I2>  *_narrow(CLASS *) ; \
  77.     static const Type_info *base_set[] ; \
  78.  
  79. // Use RTTI_SCAFFOLDING_DECL_TEMPL_3 for template classes with three
  80. // parameters. Again use this within the .h file ie: for
  81. // template <class T, int n, class Z> class foo1 { .....
  82. // use RTTI_SCAFFOLDING_DECL_TEMPL_3(foo1,T,n,Z)
  83. #define  RTTI_SCAFFOLDING_DECL_TEMPL_3(NAME,I1,I2,I3)  \
  84.     static  const Type_info info_obj ; \
  85.     virtual typeid get_info() const ; \
  86.     virtual void   *get_this_ptr(void) const ; \
  87.     static  typeid  info() ; \
  88.     static  NAME<I1,I2,I3>  *_narrow(CLASS *) ; \
  89.     static const Type_info *base_set[] ; \
  90.  
  91.  
  92.  
  93. // An useful set of macros to get the name of a particular class. The
  94. // ones without any parameters are used to get the name of a class from
  95. // within the class member functions. The other two are used to get the
  96. // name of any arbitrary class, given a pointer to an object of the class.
  97. // The macros in CAPITALS get the static class name ie: the immediate
  98. // name of the object, whereas the macros in non-capital letters get the
  99. // dynamic name of the class. Be careful and make sure that these are
  100. // use only when classes being referred to are complete (ie: not during
  101. // initialization).
  102. #define   __CLASSNAME        (GET_PTR_INFO(this))->name()
  103. #define   __classname        (GET_PTR_INFO(get_this_ptr()))->name()
  104. #define   _CLASSNAME(p)       (GET_PTR_INFO(p))->name()
  105. #define   _classname(p)       (GET_PTR_INFO(p->get_this_ptr()))->name()
  106.  
  107. // The following declarations aid in implementing the RTTI scafoolding on a
  108. // per class basis. The IMPL0, IMPL1 etc variations are geared to deal with
  109. // classes with varying sets of parents. Call these macros with only the
  110. // names of the direct base classes. They are meant for non-template
  111. // classes. In most cases, users should not have to use these macros at all.
  112. #define   NON_TEMPL_NARROW(TYPE) \
  113.      TYPE    *TYPE::_narrow(CLASS *obj) \
  114.      {   \
  115.      void   *ret =  NULL ; \
  116.      if ( ptr_cast(TYPE,obj)) \
  117.          ret = obj->get_this_ptr() ; \
  118.       return ( (TYPE *) ret) ; \
  119.      } \
  120.  
  121. #define   GET_THIS_PTR(TYPE) \
  122.      void *TYPE::get_this_ptr(void) const \
  123.       {  \
  124.     return ((void *) this);   \
  125.       }  \
  126.  
  127. // The following macro is used within other macros to form a part of the
  128. // RTTI scaffolding that goes into .c files. This again is used with non-
  129. // template classes.
  130. #define  NARROWING_MECHANISM(TYPE) \
  131.      NON_TEMPL_NARROW(TYPE) \
  132.      GET_THIS_PTR(TYPE)
  133.  
  134. // The following macros allow users to create the RTTI scaffoldings that
  135. // are a part of the class definitions (ie: they go in .c files).
  136.  
  137. // RTTI_SACFFOLDING_IMPL0 is used to prepare the definition scaffolding
  138. // for non-template classes with no parent classes.
  139. #define RTTI_SCAFFOLDING_IMPL0(TYPE) \
  140.       const Type_info TYPE::info_obj(#TYPE, 0) ;\
  141.       typeid TYPE::get_info() const { return &info_obj; } \
  142.       typeid TYPE::info() { return &info_obj; } \
  143.       NARROWING_MECHANISM(TYPE) \
  144.  
  145. // RTTI_SACFFOLDING_IMPL1 is used to prepare the definition scaffolding
  146. // for non-template classes with one parent classes ie : for
  147. // class foo : public virtual CLASS { ...
  148. // use RTTI_SCAFFOLDING_IMPL1(foo,CLASS)
  149. #define RTTI_SCAFFOLDING_IMPL1(TYPE, PARENT1) \
  150.       static const Type_info*  TYPE##_set_bases[] = \
  151.        {(const Type_info *) &PARENT1::info_obj, 0 } ; \
  152.       const  Type_info TYPE::info_obj(#TYPE, TYPE##_set_bases) ;\
  153.       typeid TYPE::get_info() const { return &info_obj; } \
  154.       typeid TYPE::info() { return &info_obj; } \
  155.       NARROWING_MECHANISM(TYPE) \
  156.  
  157. // RTTI_SACFFOLDING_IMPL2 is used to prepare the definition scaffolding
  158. // for non-template classes with two parent classes ie : for
  159. // class foo : PARENT1, PARENT2 { ...
  160. // use RTTI_SCAFFOLDING_IMPL2(foo,PARENT1,PARENT2)
  161.  
  162. #define RTTI_SCAFFOLDING_IMPL2(TYPE, PARENT1, PARENT2) \
  163.       static const Type_info*  TYPE##_set_bases[] = \
  164.          { (const Type_info *) &PARENT1::info_obj, \
  165.         (const Type_info *) &PARENT2::info_obj, 0 } ; \
  166.       const  Type_info TYPE::info_obj(#TYPE, TYPE##_set_bases) ;\
  167.       typeid TYPE::get_info() const { return &info_obj; } \
  168.       typeid TYPE::info() { return &info_obj; } \
  169.       NARROWING_MECHANISM(TYPE) \
  170.  
  171.  
  172. // RTTI_SACFFOLDING_IMPL3 is used to prepare the definition scaffolding
  173. // for non-template classes with three parent classes ie : for
  174. // class foo : PARENT1, PARENT2, PARENT3 { ...
  175. // use RTTI_SCAFFOLDING_IMPL3(foo,PARENT1,PARENT2,PARENT3)
  176.  
  177. #define RTTI_SCAFFOLDING_IMPL3(TYPE, PARENT1, PARENT2, PARENT3) \
  178.       static const Type_info*  TYPE##_set_bases[] = \
  179.        { (const Type_info *) &PARENT1::info_obj, \
  180.      (const Type_info *) &PARENT2::info_obj, \
  181.       (const Type_info *) &PARENT3::info_obj,0} ; \
  182.       const  Type_info TYPE::info_obj(#TYPE, TYPE##_set_bases) ;\
  183.       typeid TYPE::get_info() const { return &info_obj; } \
  184.       typeid TYPE::info() { return &info_obj; } \
  185.       NARROWING_MECHANISM(TYPE) \
  186.  
  187.  
  188. // RTTI_SACFFOLDING_IMPL4 is used to prepare the definition scaffolding
  189. // for non-template classes with 4 parent classes ie : for
  190. // class foo : PARENT1, PARENT2, PARENT3, PARENT4 { ...
  191. // use RTTI_SCAFFOLDING_IMPL4(foo,PARENT1,PARENT2,PARENT3,PARENT4)
  192.  
  193. #define RTTI_SCAFFOLDING_IMPL4(TYPE,PARENT1,PARENT2,PARENT3,PARENT4) \
  194.       static const Type_info*  TYPE##_set_bases[] = \
  195.       { (const Type_info *) &PARENT1::info_obj, \
  196.          (const Type_info *) &PARENT2::info_obj,  \
  197.         (const Type_info *) &PARENT3::info_obj, \
  198.         (const Type_info *) &PARENT4::info_obj, 0}; \
  199.       const  Type_info TYPE::info_obj(#TYPE, TYPE##_set_bases) ;\
  200.       typeid TYPE::get_info() const { return &info_obj; } \
  201.       typeid TYPE::info() { return &info_obj; } \
  202.       NARROWING_MECHANISM(TYPE) \
  203.  
  204. /*********************************
  205.    TEMPLATE   STRING MANIPULATION MACROS - Not necessarily decipherable
  206. **********************************/
  207.  
  208. #define    tempstr(a)       # a
  209. #define   xtempstr(a)       a
  210. #define   rest_of_initial(y)     y ## "<"
  211. #define   rest_of_final(y)       y ## ">"
  212.  
  213. #define   make_initial(x)        rest_of_initial(# x)
  214. #define   do_str(a,b)            a ## b
  215. #define   make_str(a,b)          do_str(a,b)
  216.  
  217. #define   make_first_part(a,b) make_str(make_initial(a),#b)
  218. #define   make_first_part1(a)  rest_of_initial(tempstr(a))
  219. #define   make_first_half(m,n) make_str(make_first_part(m,n), ",")
  220. #define   make_final(x)        rest_of_final( # x)
  221. #define   add_comma(x)         make_str(tempstr(x), ",")
  222.  
  223. #define   join_first_part(a,b,c)   \
  224.              make_str(make_first_half(a,b), add_comma(c))
  225.  
  226. #define MAKE2_TEMPL_PARTS(a,b,c) make_str(make_first_half(a,b),make_final(c))
  227. #define MAKE1_TEMPL_PARTS(a,b) make_str(make_first_part1(a),make_final(b))
  228. #define MAKE3_TEMPL_PARTS(a,b,c,d) \
  229.         make_str(join_first_part(a,b,c), make_final(d))
  230.  
  231.  
  232.  
  233. /*********************************
  234.    TEMPLATE      MACROS BEGIN HERE
  235. **********************************/
  236.  
  237.  
  238. /*****************************
  239.  FOLLOWING FEW MACROS ARE NOT FOR HUMAN CONSUMPTION
  240. *****************************/
  241.  
  242. #define    TEMPL_NARROWING1(TYPE,PARM1) \
  243.    template <PARM1> TYPE *TYPE::_narrow(CLASS *obj) \
  244.      {   \
  245.      void   *ret =  NULL ; \
  246.      if ( ptr_cast(TYPE,obj)) \
  247.          ret = obj->get_this_ptr() ; \
  248.       return ( (TYPE *) ret) ; \
  249.      } \
  250.   template <PARM1> void *TYPE::get_this_ptr(void) const \
  251.       {  \
  252.     return ((void *) this);   \
  253.       }  \
  254.  
  255. #define    TEMPL_NARROWING2(NAME,PARM1,PARM2,I1,I2) \
  256.    template <PARM1,PARM2> \
  257.     NAME<I1,I2> *NAME<I1,I2>::_narrow(CLASS *obj) \
  258.      {   \
  259.      void   *ret =  NULL ; \
  260.      if ( ptr_cast_2(NAME,I1,I2,obj)) \
  261.          ret = obj->get_this_ptr() ; \
  262.       return ( (NAME<I1,I2> *) ret) ; \
  263.      } \
  264.   template <PARM1,PARM2>  \
  265.     void *NAME<I1,I2>::get_this_ptr(void) const \
  266.       {  \
  267.     return ((void *) this);   \
  268.       }  \
  269.  
  270. #define    TEMPL_NARROWING3(NAME,PARM1,PARM2,PARM3,I1,I2,I3) \
  271.    template <PARM1,PARM2,PARM3> \
  272.     NAME<I1,I2,I3> *NAME<I1,I2,I3>::_narrow(CLASS *obj) \
  273.      {   \
  274.      void   *ret =  NULL ; \
  275.      if ( ptr_cast_3(NAME,I1,I2,I3,obj)) \
  276.          ret = obj->get_this_ptr() ; \
  277.       return ( (NAME<I1,I2,I3> *) ret) ; \
  278.      } \
  279.   template <PARM1,PARM2,PARM3>  \
  280.     void *NAME<I1,I2,I3>::get_this_ptr(void) const \
  281.       {  \
  282.     return ((void *) this);   \
  283.       }  \
  284.  
  285.  
  286. #define  TEMPL_RTTI_IMPL_1(TYPE,PARM1) \
  287.   template < PARM1 > typeid TYPE::get_info() const { return &info_obj; } \
  288.   template < PARM1 > typeid TYPE::info() { return &info_obj; } \
  289.   TEMPL_NARROWING1(TYPE,PARM1)
  290.  
  291. #define  TEMPL_RTTI_IMPL_2(NAME,PARM1,PARM2,I1,I2) \
  292.   template <PARM1,PARM2> \
  293.      typeid NAME<I1,I2>::get_info() const { return &info_obj; } \
  294.   template <PARM1,PARM2> \
  295.      typeid NAME<I1,I2>::info() { return &info_obj; } \
  296.   TEMPL_NARROWING2(NAME,PARM1,PARM2,I1,I2)
  297.  
  298. #define  TEMPL_RTTI_IMPL_3(NAME,PARM1,PARM2,PARM3,I1,I2,I3) \
  299.   template <PARM1,PARM2,PARM3> \
  300.      typeid NAME<I1,I2,I3>::get_info() const { return &info_obj; } \
  301.   template <PARM1,PARM2,PARM3> \
  302.      typeid NAME<I1,I2,I3>::info() { return &info_obj; } \
  303.   TEMPL_NARROWING3(NAME,PARM1,PARM2,PARM3,I1,I2,I3)
  304.  
  305.  
  306. /*****************************
  307.  FOLLOWING MACROS ARE USED TO SPECIFY IMPLEMENTATION SCAFFOLDINGS FOR
  308.     TEMPLATE CLASSES
  309. *****************************/
  310.  
  311. // The following macro are used for template classes that have no base
  312. // classes and have 1 arguments ie : for
  313. // template <class T> class foo { ...
  314. // use TEMPL_RTTI_IMPL_SCAFF_0_1(foo<T>,foo,class T)
  315. #define   TEMPL_RTTI_IMPL_SCAFF_0_1(TYPE,NAME,PARM1) \
  316.    template <PARM1> \
  317.      const Type_info  TYPE::info_obj(MAKE1_TEMPL_PARTS(NAME,PARM1), 0); \
  318.    TEMPL_RTTI_IMPL_1(TYPE,PARM1)
  319.  
  320. // The following macro are used for template classes that have no base
  321. // classes and have 2 arguments ie : for
  322. // template <class T, int n > class foo { ...
  323. // use TEMPL_RTTI_IMPL_SCAFF_0_2(foo,class T, int n , T, n)
  324. #define   TEMPL_RTTI_IMPL_SCAFF_0_2(NAME,PARM1,PARM2,I1,I2) \
  325.    template <PARM1,PARM2> const Type_info \
  326.        NAME<I1,I2>::info_obj(MAKE2_TEMPL_PARTS(NAME,PARM1,PARM2), 0) ; \
  327.    TEMPL_RTTI_IMPL_2(NAME,PARM1,PARM2,I1,I2)
  328.  
  329. // The following macro are used for template classes that have no base
  330. // classes and have 3 arguments ie : for
  331. // template <class T, int n, class Z > class foo { ...
  332. // use TEMPL_RTTI_IMPL_SCAFF_0_3(foo,class T, int n ,class Z, T, n,Z)
  333. #define   TEMPL_RTTI_IMPL_SCAFF_0_3(NAME,PARM1,PARM2,PARM3,I1,I2,I3) \
  334.  template <PARM1,PARM2,PARM3> const Type_info \
  335.   NAME<I1,I2,I3>::info_obj(MAKE3_TEMPL_PARTS(NAME,PARM1,PARM2,PARM3), 0) ; \
  336.  TEMPL_RTTI_IMPL_3(NAME,PARM1,PARM2,PARM3,I1,I2,I3)
  337.  
  338.  
  339. // The following macro are used for template classes that have 1 base
  340. // classes and have 1 arguments ie : for
  341. // template <class T > class foo : public foop<T> { ...
  342. // use TEMPL_RTTI_IMPL_SCAFF_1_1(foo<T>,foo, class T, foop<T>)
  343. #define   TEMPL_RTTI_IMPL_SCAFF_1_1(TYPE,NAME,PARM1,PARENT) \
  344.    template <PARM1> \
  345.       const Type_info *TYPE::base_set[2] = \
  346.        { (const Type_info *) &PARENT::info_obj, 0 } ; \
  347.    template <PARM1> \
  348.      const Type_info  TYPE::info_obj(MAKE1_TEMPL_PARTS(NAME,PARM1), \
  349.                            TYPE::base_set) ; \
  350.    TEMPL_RTTI_IMPL_1(TYPE,PARM1)
  351.  
  352. // The following macro are used for template classes that have 1 base
  353. // classes and have 2 arguments ie : for
  354. // template <class T,int n > class foo : public foop<T> { ...
  355. // use TEMPL_RTTI_IMPL_SCAFF_1_2(foo,class T,int n,foop<T>,T,n)
  356. #define   TEMPL_RTTI_IMPL_SCAFF_1_2(NAME,PARM1,PARM2,PARENT,I1,I2) \
  357.    template <PARM1,PARM2> \
  358.       const Type_info *NAME<I1,I2>::base_set[2] = \
  359.        { (const Type_info *) &PARENT::info_obj, 0 } ; \
  360.  template <PARM1,PARM2> const Type_info \
  361.    NAME<I1,I2>::info_obj(MAKE2_TEMPL_PARTS(NAME,PARM1,PARM2), \
  362.                           NAME<I1,I2>::base_set) ; \
  363.    TEMPL_RTTI_IMPL_2(NAME,PARM1,PARM2,I1,I2)
  364.  
  365.  
  366. // The following macro are used for template classes that have 1 base
  367. // classes and have 3 arguments ie : for
  368. // template <class T,int n,class Z > class foo : public foop<T> { ...
  369. // use TEMPL_RTTI_IMPL_SCAFF_1_3(foo,class T,int n,class Z,foop<T>,T,n,Z)
  370. #define TEMPL_RTTI_IMPL_SCAFF_1_3(NAME,PARM1,PARM2,PARM3,PARENT,I1,I2,I3) \
  371.  template <PARM1,PARM2,PARM3> \
  372.     const Type_info *NAME<I1,I2,I3>::base_set[2] = \
  373.        { (const Type_info *) &PARENT::info_obj, 0 } ; \
  374. template <PARM1,PARM2,PARM3> const Type_info \
  375.   NAME<I1,I2,I3>::info_obj(MAKE3_TEMPL_PARTS(NAME,PARM1,PARM2,PARM3), \
  376.                        NAME<I1,I2,I3>::base_set) ; \
  377.  TEMPL_RTTI_IMPL_3(NAME,PARM1,PARM2,PARM3,I1,I2,I3)
  378.  
  379.  
  380. // The following macro are used for template classes that have 2 base
  381. // classes and have 1 arguments ie : for
  382. // template <class T > class foo : foop1<T>, foop2<T> { ...
  383. // use TEMPL_RTTI_IMPL_SCAFF_2_1(foo<T>,foo, class T, foop1<T>,foop2<T>)
  384. #define   TEMPL_RTTI_IMPL_SCAFF_2_1(TYPE,NAME,PARM1,P1,P2) \
  385.    template <PARM1> \
  386.       const Type_info *TYPE::base_set[3] = \
  387.        { (const Type_info *) &P1::info_obj, \
  388.      (const Type_info *) &P2::info_obj, 0 } ; \
  389.    template <PARM1> \
  390.      const Type_info  TYPE::info_obj(MAKE1_TEMPL_PARTS(NAME,PARM1), \
  391.                            TYPE::base_set) ; \
  392.    TEMPL_RTTI_IMPL_1(TYPE,PARM1)
  393.  
  394.  
  395. // The following macro are used for template classes that have 2 base
  396. // classes and have 2 arguments ie: for
  397. // template <class T,int n > class foo : foop1<T>,foop2<T> { ...
  398. // use TEMPL_RTTI_IMPL_SCAFF_2_2(foo,class T,int n,foop1<T>,foop2<T>,T,n)
  399. #define   TEMPL_RTTI_IMPL_SCAFF_2_2(NAME,PARM1,PARM2,P1,P2,I1,I2) \
  400.    template <PARM1,PARM2> \
  401.       const Type_info *NAME<I1,I2>::base_set[3] = \
  402.        { (const Type_info *) &P1::info_obj, \
  403.      (const Type_info *) &P2::info_obj, 0 } ; \
  404.    template <PARM1,PARM2> const Type_info\
  405.      NAME<I1,I2>::info_obj(MAKE2_TEMPL_PARTS(NAME,PARM1,PARM2), \
  406.                          NAME<I1,I2>::base_set) ; \
  407.    TEMPL_RTTI_IMPL_2(NAME,PARM1,PARM2,I1,I2)
  408.  
  409. // The following macro are used for template classes that have 2 base
  410. // classes and have 3 arguments ie: for
  411. // template <class T,int n,class Z > class foo : foop1<T>,foop2<T> { ...
  412. // use TEMPL_RTTI_IMPL_SCAFF_2_3(foo,class T,int n,class Z,foop1<T>,foop2<T>,T,n,Z)
  413. #define   TEMPL_RTTI_IMPL_SCAFF_2_3(NAME,PRM1,PRM2,PRM3,P1,P2,I1,I2,I3) \
  414.    template <PRM1,PRM2,PRM3> \
  415.       const Type_info *NAME<I1,I2,I3>::base_set[3] = \
  416.        { (const Type_info *) &P1::info_obj, \
  417.      (const Type_info *) &P2::info_obj, 0 } ; \
  418. template <PRM1,PRM2,PRM3> const Type_info \
  419.   NAME<I1,I2,I3>::info_obj(MAKE3_TEMPL_PARTS(NAME,PRM1,PRM2,PRM3), \
  420.                      NAME<I1,I2,I3>::base_set) ; \
  421.    TEMPL_RTTI_IMPL_3(NAME,PRM1,PRM2,PRM3,I1,I2,I3)
  422.  
  423.  
  424. // The following macro are used for template classes that have 3 base
  425. // classes and have 1 arguments ie: for
  426. // template <class T > class foo : foop1<T>, foop2<T>,foop3<T> { ...
  427. // use TEMPL_RTTI_IMPL_SCAFF_3_1(foo<T>,foo, class T,foop1<T>,foop2<T>,foop3<T>)
  428. #define   TEMPL_RTTI_IMPL_SCAFF_3_1(TYPE,NAME,PARM1,P1,P2,P3) \
  429.    template <PARM1> \
  430.       const Type_info *TYPE::base_set[4] = \
  431.        { (const Type_info *) &P1::info_obj, \
  432.      (const Type_info *) &P2::info_obj, \
  433.      (const Type_info *) &P3::info_obj, 0 } ; \
  434.    template <PARM1> \
  435.      const Type_info  TYPE::info_obj(MAKE1_TEMPL_PARTS(NAME,PARM1), \
  436.                            TYPE::base_set) ; \
  437.    TEMPL_RTTI_IMPL_1(TYPE,PARM1)
  438.  
  439. // The following macro are used for template classes that have 3 base
  440. // classes and have 2 arguments ie: for
  441. // template <class T,int n > class foo : foop1<T>,foop2<T>,foop3<T> { ...
  442. // use TEMPL_RTTI_IMPL_SCAFF_3_2(foo,class T,int n,foop1<T>,foop2<T>,foop3<T>,T,n)
  443.  
  444. #define   TEMPL_RTTI_IMPL_SCAFF_3_2(NAME,PARM1,PARM2,P1,P2,P3,I1,I2) \
  445.    template <PARM1,PARM2> \
  446.       const Type_info *NAME<I1,I2>::base_set[4] = \
  447.        { (const Type_info *) &P1::info_obj, \
  448.      (const Type_info *) &P2::info_obj, \
  449.      (const Type_info *) &P3::info_obj, 0 } ; \
  450.    template <PARM1,PARM2> const Type_info \
  451.      NAME<I1,I2>::info_obj(MAKE2_TEMPL_PARTS(NAME,PARM1,PARM2), \
  452.                    NAME<I1,I2>::base_set) ; \
  453.    TEMPL_RTTI_IMPL_2(NAME,PARM1,PARM2,I1,I2)
  454.  
  455. // The following macro are used for template classes that have 3 base
  456. // classes and have 3 arguments ie: for
  457. // template <class T,int n,class Z> class foo : foop1<T>,foop2<T>,foop3<T> { ...
  458. // use TEMPL_RTTI_IMPL_SCAFF_3_3(foo,class T,int n,class Z,foop1<T>,foop2<T>,foop3<T>,T,n,Z)
  459.  
  460. #define TEMPL_RTTI_IMPL_SCAFF_3_3(NAME,PRM1,PRM2,PRM3,P1,P2,P3,I1,I2,I3) \
  461.    template <PRM1,PRM2,PRM3> \
  462.       const Type_info *NAME<I1,I2,I3>::base_set[4] = \
  463.        { (const Type_info *) &P1::info_obj, \
  464.      (const Type_info *) &P2::info_obj, \
  465.      (const Type_info *) &P3::info_obj, 0 } ; \
  466. template <PRM1,PRM2,PRM3> const Type_info\
  467.   NAME<I1,I2,I3>::info_obj(MAKE3_TEMPL_PARTS(NAME,PRM1,PRM2,PRM3), \
  468.                        NAME<I1,I2,I3>::base_set) ; \
  469.    TEMPL_RTTI_IMPL_3(NAME,PRM1,PRM2,PRM3,I1,I2,I3)
  470.  
  471.  
  472. #endif //    _H_RTTI_MACROS
  473.